# Coding:utf-8

from pydantic import Field
from typing import Optional
import pandas as pd
import time
import numpy as np
import io
import contextlib

from utils.utils import time2str

class DataAnalysisClass:
    data: Optional[pd.DataFrame] = Field(None)
    # data: None

    def quick_describe(self):
        try:
            # 创建一个 StringIO 对象
            output_buffer = io.StringIO()
            # 数值型变量分析
            numericl_cols = self.data.select_dtypes(include=[np.number]).columns

            # 分类型变量分析
            categorical_cols = self.data.select_dtypes(include=["object", "category"]).columns

            # 时间序列分析
            datetime_cols = self.data.select_dtypes(include=["datetime64"]).columns

            with contextlib.redirect_stdout(output_buffer):
                print("="*50)
                print(f"行数：{self.data.shape[0]},列数：{self.data.shape[1]}")
                print("\n列名及数据类型：")
                print(f"{self.data.dtypes}")
                if len(numericl_cols) > 0:
                    print("\n"+"="*50)
                    print("数值型变量统计量描述：")
                    print(f"{self.data[numericl_cols].describe()}")

                if len(categorical_cols) > 0:
                    print("\n"+"="*50)
                    print("分类型变量分析：")
                    for col in categorical_cols:
                        print(f"\n{col}：")
                        print(f"唯一值数量：{self.data[col].nunique()}")
                        print("前5个最常见值及其频数：")
                        print(self.data[col].value_counts().head())

                if len(datetime_cols) > 0:
                    print("\n"+"="*50)
                    print("时间序列分析：")
                    for col in datetime_cols:
                        print("\n{col}：")
                        print(f"时间范围：{self.data[col].min()}至{self.data[col].max()}")
                        print(f"时间跨度：{self.data[col].max()-self.data[col].min()}")

            # 获取 StringIO 中的内容
            output = output_buffer.getvalue()
            output_buffer.close() # 关闭 StringIO 对象
            
            return output
        except Exception as e:
            raise Exception(f"read_data error: {str(e)}, time: {time2str(time.time())}")